﻿using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Sustainalytics.DataLayer;
using Sustainalytics.Entities;
using Sustainalytics.Replication.Publisher;
using Sustainalytics.Utils;
using Ent = Sustainalytics.Entities;

namespace Sustainalytics.News.BusinessLogic
{
    public class NotificationsManagement : INotificationsManagement
    {
        private INotificationsRepository _notificationsRepo { get; set; }
        private ServiceBusPublisher _serviceBusPublisher { get; set; }

        public NotificationsManagement(INotificationsRepository notificationsRepo, ServiceBusPublisher serviceBus)
        {
            this._notificationsRepo = notificationsRepo;
            this._serviceBusPublisher = serviceBus;
        }

        public static INotificationsManagement GetInstance(INotificationsRepository notificationsRepo, ServiceBusPublisher serviceBus)
        {
            return new NotificationsManagement(notificationsRepo, serviceBus);
        }

        public Ent.Notifications GetNotification()
        {
            try
            {
                NewsServiceSerilog.Log.GetNotification();

                Ent.Notifications notification = _notificationsRepo.GetNotification();

                NewsServiceSerilog.Log.GetNotificationSuccess();

                return notification;
            }
            catch (Exception ex)
            {
                NewsServiceSerilog.Log.GetNotificationError(ex);
                throw;
            }
        }

        public Ent.Notifications UpsertNotification(Ent.Notifications notification)
        {
            string argsStr = LogArgument.GetString(notification);

            try
            {
                NewsServiceSerilog.Log.UpsertNotification(argsStr);

                //validation rules
                ValidateNotification(notification);

                //update repository
                _notificationsRepo.UpsertNotification(notification);

                var updatedNotification = _notificationsRepo.GetNotification();

                //serialize the updated notification to another region through ServiceBus
                _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(updatedNotification), ReplicationUtils.EntityType.Notification, ReplicationUtils.Operation.Update);

                NewsServiceSerilog.Log.UpsertNotificationSuccess(argsStr);
                
                return updatedNotification;
            }
            catch (Exception ex)
            {
                NewsServiceSerilog.Log.UpsertNotificationError(argsStr, ex);
                throw;
            }
        }

        public static void ValidateNotification(Ent.Notifications notification)
        {
            var validationExList = new List<NotificationValidationException>();

            if (notification == null) throw new NotificationNullException();

            //body
            if (string.IsNullOrEmpty(notification.Body)) validationExList.Add(new NotificationValidationBodyNullOrEmptyException());

            //check if status is one of the defined enumerables
            if (!Enum.GetValues(typeof(NotificationsStatus)).Cast<int>().Any(x => x == (int)notification.Status))
                validationExList.Add(new NotificationValidationStatusNotValidException());

            //overall
            if (validationExList.Any()) throw new NotificationNotValidException(validationExList.ToArray());
        }
    }
}
